package vn.evolus.pencil.service.impl;

import java.util.ArrayList;

import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.transaction.annotation.Transactional;

import vn.evolus.commons.data.IRepository;
import vn.evolus.commons.query.Expression;
import vn.evolus.pencil.model.Role;
import vn.evolus.pencil.model.User;
import vn.evolus.pencil.service.RoleService;
import vn.evolus.pencil.service.UserService;

public class UserServiceImpl implements UserService {

	private PasswordEncoder passwordEncoder;
	private SaltSource saltSource;
	private IRepository repository;
	private RoleService roleService;

	public UserServiceImpl(PasswordEncoder passwordEncoder,
			SaltSource saltSource, IRepository repository,
			RoleService roleService) {
		this.passwordEncoder = passwordEncoder;
		this.saltSource = saltSource;
		this.repository = repository;
		this.roleService = roleService;

	}

	private String hashPassword(String password, User user) {
		org.springframework.security.core.userdetails.User tempUserDetails = new org.springframework.security.core.userdetails.User(
				user.getUsername(), "fakePassword", true, true, true, true,
				new ArrayList<GrantedAuthority>());
		return passwordEncoder.encodePassword(password,
				saltSource.getSalt(tempUserDetails));
	}

	@Override
	@Transactional
	public void saveUser(User user) {
		user.setUsername(user.getUsername().toLowerCase());
		user.setDisplayName(user.getUsername().toLowerCase());
		user.setEmail(user.getEmail().toLowerCase());
		user.setPassword(hashPassword(user.getPassword(), user));

		Role userRole = roleService.getUserRole();
		user.getRoles().add(userRole);

		repository.save(user);
	}

	@Override
	public void deleteUser(User user) {
		// TODO Auto-generated method stub
	}

	@Override
	public void saveAdminUser(User user) {
		// TODO Auto-generated method stub
	}

	@Override
	@Transactional
	public User getCurrentUser() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication == null) {
			return null;
		}

		Object principal = authentication.getPrincipal();
		if (principal == null) {
			return null;
		}
		if (principal instanceof UserDetails) {
			UserDetails userdetails = (UserDetails) principal;
			String username = userdetails.getUsername();
			User user = repository.getByKey(User.class, "username", username);

			return user;
		}

		return null;
	}

	@Override
	@Transactional
	public User getUserById(long id) {
		return repository.getFirst(User.class, Expression.eq("id", id));
	}

	@Override
	@Transactional
	public void updateUser(User user) {
		repository.update(user);
	}
}
